/************************************************************
 * Copyright (C), 2009-2011,  Tech. Co., Ltd.
 * FileName:        // 文件名
 * Author:          // 作者
 * Date:            // 日期
 * Description:     // 模块描述
 * Version:         // 版本信息
 * Function List:   // 主要函数及其功能
 *     1. -------
 * History:         // 历史修改记录
 *     <author>  <time>   <version >   <desc>
 *     xxxxx    16/10/12     1.0     build this moudle
 ***********************************************************/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define bool unsigned char
int init_i2c(int i2cbus);
void I2C_Write_Byte(unsigned char RegAddr,unsigned char data);
unsigned char I2C_Read_Byte(unsigned char RegAddr);
bool I2C_Write_ByteN(u8 RegAddr, u8 *data, u16 Num);
int msleep(unsigned int ms);
#define Delay_ms msleep
#define _DEBUG_MODE_
#ifndef  _DEBUG_MODE_
#define Debug_Printf(format,...)
#else
#define Debug_Printf printf
#endif

// LT8618SX RGB 输入，HDMI输出，寄存器设置
//#define   LT8618SX_ADR        0x76                    // IIC Address，If CI2CA pins are high(2800mV~3300mV)
#define   LT8618SX_ADR 0x72                     // IIC Address，If CI2CA pins are low(0~400mV)

bool flag_Ver_u3 = 0;

#define LT8618SXB_I2C_Write_Byte I2C_Write_Byte
#define HDMI_WriteI2C_Byte I2C_Write_Byte

#define LT8618SXB_I2C_Read_Byte I2C_Read_Byte
#define HDMI_ReadI2C_Byte I2C_Read_Byte

//--------------------------------------------------

//#define _DVI_ // DVI output (no audio)
#define _HDMI_ // HDMI output


/*--------------------------------
   CI2CA            I2C address
   -----------------------
   (0~400mV)----------0x72(default)
   (400mV~800mV)------0x7a
   (800mV~1200mV)-----0x90
   (1200mV~1600mV)----0x92

   (2000mV~2400mV)----0x94
   (2400mV~2800mV)----0x7e
   (2800mV~3300mV)----0x76
   -----------------------------------*/


/***************************************************

   要注意的是IIC地址0x72(0x76)的最低位bit0是读写标志位，如果是Linux系统的IIC，最高位是读写标志位，IIC地址需要右移一位，IIC地址变成0x39(0x3B).

   IIC 速率不要超过100K

   如果LT8618SXB 的IIC 地址不是0x72;需要用主控的GPIO 去复位LT8618SXB，先拉低100ms，再拉高，delay100ms，再初始化LT8618SXB寄存器。

   The lowest bit 0 of the IIC address 0x72 (0x76) of LT8618SXB is the read-write flag bit.
   In the case of Linux IIC, the highest bit is the read-write flag bit, The IIC address needs to be moved one bit to the right, and the IIC address becomes 0x39 (0x3B).

   IIC rate should not exceed 100K.

   If the IIC address of LT8618SXB is not 0x72, you need to reset LT8618SXB with the master GPIO, pull down 100ms, then pull up, delay 100ms, and initialize the LT8618SXB register.

 ****************************************************/



//--------------------------------------------------

//Input rgb888 synchronization signal:
#define _DE_Sync_mode_                                  // DE + Hsync + Vsync
//#define _HV_mode_Only_ // only Hsync + Vsync, no DE
//#define _De_mode_Only_ // only DE, no Hsync & Vsync

//--------------------------------------------------

// RGB888 channel Swap
#define _TTL_BGR_   0x70                                // B0~B7[D0:D7];G0~G7[D8:D15];R0~R7[D16:D23];
#define _TTL_GBR_   0x60                                // G0~G7[D0:D7];B0~B7[D8:D15];R0~R7[D16:D23];

#define _TTL_BRG_   0x50                                // B0~B7[D0:D7];R0~R7[D8:D15];G0~G7[D16:D23];
#define _TTL_RBG_   0x40                                // R0~R7[D0:D7];B0~B7[D8:D15];G0~G7[D16:D23];

#define _TTL_GRB_   0x30                                // G0~G7[D0:D7];R0~R7[D8:D15];B0~B7[D16:D23];
#define _TTL_RGB_   0x00                                // R0~R7[D0:D7];G0~G7[D8:D15];B0~B7[D16:D23];

/****************************************************/

// #define _LT8618_HDCP_ // If HDMI encrypted output is not required, mask this macro definition

/****************************************************/
u8  I2CADR = LT8618SX_ADR;                  // IIC address

u16 hfp, hs_width, hbp, h_act, h_tal, v_act, v_tal, vfp, vs_width, vbp;

u32 CLK_Cnt;

u8  USE_DDRCLK; // 1: DDR mode; 0: SDR (normal) mode

#ifdef _Read_TV_EDID_

u8  Sink_EDID[256];

u8  Sink_EDID2[256];

#endif

u8 VIC_Num; // vic ,0x10: 1080P ;  0x04 : 720P ;

/**************************************/

enum {
    _32KHz = 0,
    _44d1KHz,
    _48KHz,

    _88d2KHz,
    _96KHz,
    _176Khz,
    _196KHz
};

u16 IIS_N[] =
{
    4096,                   // 32K
    6272,                   // 44.1K
    6144,                   // 48K
    12544,                  // 88.2K
    12288,                  // 96K
    25088,                  // 176K
    24576                   // 196K
};

u8 Sample_Freq[] =
{
    0x30,                   // 32K
    0x00,                   // 44.1K
    0x20,                   // 48K
    0x80,                   // 88.2K
    0xa0,                   // 96K
    0xc0,                   // 176K
    0xe0                    //  196K
};

//************************************/

u8 Resolution_Num;

//#ifdef _Ver_U3_
static u8 LT8618SXB_PLL_u3[3][3] =
{
    { 0x00, 0x9e, 0xaa },   // < 50MHz
    { 0x00, 0x9e, 0x99 },   // 50 ~ 100M
    { 0x00, 0x9e, 0x88 },   // > 100M
};
//#else  // u2 version
static u8 LT8618SXB_PLL_u2[3][3] =
{
    { 0x00, 0x94, 0xaa },   // < 50MHz
    { 0x01, 0x94, 0x99 },   // 50 ~ 100M
    { 0x03, 0x94, 0x88 },   // > 100M
};

//#endif

enum
{
    _Less_than_50M = 0x00,
    _Bound_50_100M,
    _Greater_than_100M
};

u8 CLK_bound;

//*******************************************************************//

#define _16_9_  0x2A                                                                                            // 16:9
#define _4_3_   0x19                                                                                            // 4:3

#ifndef _DE_Sync_mode_                                                                                          // Only Hsync and Vsync synchronization signals, no DE synchronization signal

static u32 Format_Timing[][14] =
{
//  H_FP /  H_sync / H_BP / H_act / H_total / V_FP / V_sync / V_BP / V_act / V_total / Vic / Pic_Ratio / Clk_bound(SDR) / Clk_bound(DDR)

// /*------------------------------------------------    ---*/  Vic / Pic_Ratio / Clk_bound(SDR) / Clk_bound(DDR)
    { 16,   62,  60,  720,  858,  9, 6,  30, 480,  525,  2,  _4_3_,  _Less_than_50M,     _Less_than_50M     },  // 480P 60Hz 27MHz
    { 12,   64,  68,  720,  864,  5, 5,  39, 576,  625,  17, _4_3_,  _Less_than_50M,     _Less_than_50M     },  // 576P 50Hz 27MHz

    { 110,  40,  220, 1280, 1650, 5, 5,  20, 720,  750,  4,  _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 720P 60Hz 74.25MHz
    { 440,  40,  220, 1280, 1980, 5, 5,  20, 720,  750,  19, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 720P 50Hz 74.25MHz
    { 1760, 40,  220, 1280, 3300, 5, 5,  20, 720,  750,  62, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 720P 30Hz 74.25MHz
    { 2420, 40,  220, 1280, 3960, 5, 5,  20, 720,  750,  61, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 720P 25Hz 74.25MHz

    { 88,   44,  148, 1920, 2200, 4, 5,  36, 1080, 1125, 16, _16_9_, _Greater_than_100M, _Bound_50_100M     },  // 1080P  60Hz 148.5MHz
    { 528,  44,  148, 1920, 2640, 4, 5,  36, 1080, 1125, 31, _16_9_, _Greater_than_100M, _Bound_50_100M     },  // 1080P  50Hz 148.5MHz
    { 88,   44,  148, 1920, 2200, 4, 5,  36, 1080, 1125, 34, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 1080P  30Hz 74.25MHz
    { 528,  44,  148, 1920, 2640, 4, 5,  36, 1080, 1125, 33, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 1080P  25Hz 74.25MHz

    { 88,   44,  148, 1920, 2200, 2, 5,  15, 540,  562,  5,  _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 1080i  60Hz 74.25MHz
    { 528,  44,  148, 1920, 2640, 2, 5,  15, 540,  562,  20, _16_9_, _Bound_50_100M,     _Less_than_50M     },  // 1080i  50Hz 74.25MHz

    { 176,  88,  296, 3840, 4400, 8, 10, 72, 2160, 2250, 95, _16_9_, _Greater_than_100M, _Greater_than_100M },  // 4K 30Hz  297MHz

    { 40,   128, 88,  800,  1056, 1, 4,  23, 600,  628,  0,  _4_3_,  _Less_than_50M,     _Less_than_50M     },  // VESA 800x600 40MHz
    { 24,   136, 160, 1024, 1344, 3, 6,  29, 768,  806,  0,  _4_3_,  _Bound_50_100M,     _Less_than_50M     },  // VESA 1024X768 65MHz
    { 24,   136, 160, 1024, 1344, 3, 6,  29, 768,  806,  0,  _4_3_,  _Bound_50_100M,     _Less_than_50M     },  // VESA 1024X600 51MHz


/*
   {},
   {},
   {},
   {},
   //*/
};

enum
{
    H_fp = 0,
    H_sync,
    H_bp,
    H_act,
    H_tol,

    V_fp,
    V_sync,
    V_bp,
    V_act,
    V_tol,

    Vic,

    Pic_Ratio,      // Image proportion

    Clk_bound_SDR,  // SDR
    Clk_bound_DDR   // DDR
};

#else // There are Hsync, Vsync and DE synchronization signals

static u32 Format_Timing[][4] =
{
//  H_FP /  H_sync / H_BP / H_act / H_total / V_FP / V_sync / V_BP / V_act / V_total / Vic / Pic_Ratio / Clk_bound(SDR) / Clk_bound(DDR)

// /*------------------------------------------------    ---*/  Vic / Pic_Ratio / Clk_bound(SDR) / Clk_bound(DDR)
    { /* 16,     62,  60,  720,  858,  9, 6,  30, 480,  525,  */2,    _4_3_,  _Less_than_50M,     _Less_than_50M     }, // 480P 60Hz 27MHz
    { /* 12,     64,  68,  720,  864,  5, 5,  39, 576,  625,  */17,   _4_3_,  _Less_than_50M,     _Less_than_50M     }, // 576P 50Hz 27MHz

    { /* 110,    40,  220, 1280, 1650, 5, 5,  20, 720,  750,  */4,   _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 720P 60Hz 74.25MHz
    { /* 440,    40,  220, 1280, 1980, 5, 5,  20, 720,  750,  */19,  _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 720P 50Hz 74.25MHz
    { /* 1760, 40,  220, 1280, 3300, 5, 5,  20, 720,    750,  */62,  _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 720P 30Hz 74.25MHz
    { /* 2420, 40,  220, 1280, 3960, 5, 5,  20, 720,    750,  */61,  _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 720P 25Hz 74.25MHz

    { /* 88,     44,  148, 1920, 2200, 4, 5,  36, 1080, 1125, */16,  _16_9_, _Greater_than_100M, _Bound_50_100M     }, // 1080P  60Hz 148.5MHz
    { /* 528,    44,  148, 1920, 2640, 4, 5,  36, 1080, 1125, */31, _16_9_, _Greater_than_100M, _Bound_50_100M     }, // 1080P  50Hz 148.5MHz
    { /* 88,     44,  148, 1920, 2200, 4, 5,  36, 1080, 1125, */34,  _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 1080P  30Hz 74.25MHz
    { /* 528,    44,  148, 1920, 2640, 4, 5,  36, 1080, 1125, */33, _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 1080P  25Hz 74.25MHz

    { /* 88,     44,  148, 1920, 2200, 2, 5,  15, 540,  562,  */5,    _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 1080i  60Hz 74.25MHz
    { /* 528,    44,  148, 1920, 2640, 2, 5,  15, 540,  562,  */20,  _16_9_, _Bound_50_100M,     _Less_than_50M     }, // 1080i  50Hz 74.25MHz

    { /* 176,    88,  296, 3840, 4400, 8, 10, 72, 2160, 2250, */95, _16_9_, _Greater_than_100M, _Greater_than_100M }, // 4K 30Hz    297MHz

    { /* 40,     128, 88,  800,  1056, 1, 4,  23, 600,  628,  */0,    _4_3_,  _Less_than_50M,     _Less_than_50M     }, // VESA 800x600 40MHz
    { /* 24,     136, 160, 1024, 1344, 3, 6,  29, 768,  806,  */0,    _4_3_,  _Bound_50_100M,     _Less_than_50M     }, // VESA 1024X768 65MHz
    { /* 24,     136, 160, 1024, 1344, 3, 6,  29, 768,  806,  */0,    _4_3_,  _Bound_50_100M,     _Less_than_50M     }, // VESA 1024X600 51MHz


/*
   {},
   {},
   {},
   {},
   //*/
};

enum
{
//  H_fp = 0,
//  H_sync,
//  H_bp,
//  H_act,
//  H_tol,

//  V_fp,
//  V_sync,
//  V_bp,
//  V_act,
//  V_tol,

    Vic = 0,

    Pic_Ratio,      // Image proportion

    Clk_bound_SDR,  // SDR
    Clk_bound_DDR   // DDR
};

#endif

//*******************************************************************//

enum
{
    _480P60_ = 0,
    _576P50_,

    _720P60_,
    _720P50_,
    _720P30_,
    _720P25_,

    _1080P60_,
    _1080P50_,
    _1080P30_,
    _1080P25_,

    _1080i60_,
    _1080i50_,

    _4K30_,

    _800x600P60_,
    _1024x768P60_,
    _1024x600P60_
};

//==========================================================//

#ifdef _LT8618_HDCP_
/***********************************************************/

void LT8618SXB_HDCP_Init(void)                     //luodexing
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x80);
    LT8618SXB_I2C_Write_Byte(0x13, 0xfe);
    LT8618SXB_I2C_Write_Byte(0x13, 0xff);

    LT8618SXB_I2C_Write_Byte(0x14, 0x00);
    LT8618SXB_I2C_Write_Byte(0x14, 0xff);

    LT8618SXB_I2C_Write_Byte(0xff, 0x85);
    LT8618SXB_I2C_Write_Byte(0x07, 0x1f);
    LT8618SXB_I2C_Write_Byte(0x13, 0xfe);             // [7]=force_hpd, [6]=force_rsen, [5]=vsync_pol, [4]=hsync_pol,
    // [3]=hdmi_mode, [2]=no_accs_when_rdy, [1]=skip_wt_hdmi
    LT8618SXB_I2C_Write_Byte(0x17, 0x0f);             // [7]=ri_short_read, [3]=sync_pol_mode, [2]=srm_chk_done,
    // [1]=bksv_srm_pass, [0]=ksv_list_vld
    LT8618SXB_I2C_Write_Byte(0x15, 0x05);
    //LT8618SXB_I2C_Write_Byte(0x15,0x65);// [7]=key_ddc_st_sel, [6]=tx_hdcp_en,[5]=tx_auth_en, [4]=tx_re_auth
}

/***********************************************************/

void LT8618SXB_HDCP_Enable(void)                      //luodexing
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x80);
    LT8618SXB_I2C_Write_Byte(0x14, 0x00);
    LT8618SXB_I2C_Write_Byte(0x14, 0xff);

    LT8618SXB_I2C_Write_Byte(0xff, 0x85);
    LT8618SXB_I2C_Write_Byte(0x15, 0x01);             //disable HDCP
    LT8618SXB_I2C_Write_Byte(0x15, 0x71);             //enable HDCP
    LT8618SXB_I2C_Write_Byte(0x15, 0x65);             //enable HDCP
}

/***********************************************************/

void LT8618SXB_HDCP_Disable(void)                     //luodexing
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x85);
    LT8618SXB_I2C_Write_Byte(0x15, 0x45);             //enable HDCP
}

#endif


/***********************************************************

***********************************************************/

void LT8918SXB_Read_EDID(void)
{
#ifdef _Read_TV_EDID_

    u8  i, j;
    u8  extended_flag = 0x00;

    LT8618SXB_I2C_Write_Byte(0xff, 0x85);
    //LT8618SXB_I2C_Write_Byte(0x02,0x0a); //I2C 100K
    LT8618SXB_I2C_Write_Byte(0x03, 0xc9);
    LT8618SXB_I2C_Write_Byte(0x04, 0xa0);                 //0xA0 is EDID device address
    LT8618SXB_I2C_Write_Byte(0x05, 0x00);                 //0x00 is EDID offset address
    LT8618SXB_I2C_Write_Byte(0x06, 0x20);                 //length for read
    LT8618SXB_I2C_Write_Byte(0x14, 0x7f);

    for(i = 0; i < 8; i++)                                // block 0 & 1
    {
        LT8618SXB_I2C_Write_Byte(0x05, i * 32);           //0x00 is EDID offset address
        LT8618SXB_I2C_Write_Byte(0x07, 0x36);
        LT8618SXB_I2C_Write_Byte(0x07, 0x34);             //0x31
        LT8618SXB_I2C_Write_Byte(0x07, 0x37);             //0x37
        Delay_ms(5);                                      // wait 5ms for reading edid data.
        if(LT8618SXB_I2C_Read_Byte(0x40) & 0x02)        //KEY_DDC_ACCS_DONE=1
        {
            if(LT8618SXB_I2C_Read_Byte(0x40) & 0x50)    //DDC No Ack or Abitration lost
            {
                Debug_Printf("read edid failed: no ack");
                goto end;
            }else
            {
                Debug_Printf("");
                for(j = 0; j < 32; j++)
                {
                    Sink_EDID[i * 32 + j] = LT8618SXB_I2C_Read_Byte(0x83);
                    Debug_Printf("", Sink_EDID[i * 32 + j]);

                    //  edid_data = LT8618SXB_I2C_Read_Byte(0x83);

                    if((i == 3) && (j == 30))
                    {
                        //  extended_flag = edid_data & 0x03;
                        extended_flag = Sink_EDID[i * 32 + j] & 0x03;
                    }
                    //  Debug_Printf("%02bx,", edid_data);
                }
                if(i == 3)
                {
                    if(extended_flag < 1) //no block 1, stop reading edid.
                    {
                        goto end;
                    }
                }
            }
        }else
        {
            Debug_Printf("read edid failed: accs not done");
            goto end;
        }
    }

    if(extended_flag < 2)                                 //no block 2, stop reading edid.
    {
        goto end;
    }

    for(i = 0; i < 8; i++)                                //  // block 2 & 3
    {
        LT8618SXB_I2C_Write_Byte(0x05, i * 32);           //0x00 is EDID offset address
        LT8618SXB_I2C_Write_Byte(0x07, 0x76);             //0x31
        LT8618SXB_I2C_Write_Byte(0x07, 0x74);             //0x31
        LT8618SXB_I2C_Write_Byte(0x07, 0x77);             //0x37
        Delay_ms(5);                                      // wait 5ms for reading edid data.
        if(LT8618SXB_I2C_Read_Byte(0x40) & 0x02)        //KEY_DDC_ACCS_DONE=1
        {
            if(LT8618SXB_I2C_Read_Byte(0x40) & 0x50)    //DDC No Ack or Abitration lost
            {
                Debug_Printf("read edid failed: no ack");
                goto end;
            }else
            {
                Debug_Printf("");
                for(j = 0; j < 32; j++)
                {
                    Sink_EDID2[i * 32 + j] = LT8618SXB_I2C_Read_Byte(0x83);
                    Debug_Printf("", Sink_EDID2[i * 32 + j]);

                    //  edid_data = LT8618SXB_I2C_Read_Byte(0x83);
                    //  Debug_Printf("%02bx,", edid_data);
                }
                if(i == 3)
                {
                    if(extended_flag < 3) //no block 1, stop reading edid.
                    {
                        goto end;
                    }
                }
            }
        }else
        {
            Debug_Printf("read edid failed: accs not done");
            goto end;
        }
    }
    //Debug_Printf("read edid succeeded, checksum = ",Sink_EDID[255]);
end:
    LT8618SXB_I2C_Write_Byte(0x03, 0xc2);
    LT8618SXB_I2C_Write_Byte(0x07, 0x1f);
#endif
}

/***********************************************************

***********************************************************/
void LT8618SXB_Reset(void)
{
#if 0
    GPIO_WriteLow(GPIOD, GPIO_PIN_2);     // Low
    Delay_ms(100);
    GPIO_WriteHigh(GPIOD, GPIO_PIN_2);    // High
    Delay_ms(100);
    Debug_Printf("VOB SKIP reset\n");
#else
    Debug_Printf("VOB Do reset\n");
    system("i2cset -f -y 2 0x20 0x0b 0x01");
    msleep(1000);
    msleep(1000);
#endif
}

//------------------------------------------------------------

void LT8618SXB_Chip_ID(void)
{
    u8 id0, id1, id2;

    LT8618SXB_I2C_Write_Byte(0xFF, 0x80);                                       // register bank
    LT8618SXB_I2C_Write_Byte(0xee, 0x01);

    while((id0 != 0x17) || (id1 != 0x02) || ((id2 & 0xfc) != 0xe0))
    {
        id0    = LT8618SXB_I2C_Read_Byte(0x00);
        id1    = LT8618SXB_I2C_Read_Byte(0x01);
        id2    = LT8618SXB_I2C_Read_Byte(0x02);
        Delay_ms(100);
    }

#ifdef _DEBUG_MODE_
//  Debug_Printf("Read LT8618SXB ID ");
    Debug_Printf("LT8618SXB Chip ID = %02x%02x%02x\n",  LT8618SXB_I2C_Read_Byte(0x00)     // 0x17
                                                        , LT8618SXB_I2C_Read_Byte(0x01)                           // 0x02
                                                        , LT8618SXB_I2C_Read_Byte(0x02));                           // 0xE1 / 0xE2
#endif


/********************

   _Ver_U2 ID: 0x17 0x02 0xE1

   _Ver_U3 ID: 0x17 0x02 0xE2

 *********************/
    if(id2 == 0xe2)
    {
        flag_Ver_u3 = 1;    // u3
    }else
    if(id2 == 0xe1)
    {
        flag_Ver_u3 = 0;    // u2
    }
}

/***********************************************************

***********************************************************/

void LT8618SXB_RST_PD_Init(void)
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x80);
    LT8618SXB_I2C_Write_Byte(0x11, 0x00); //reset MIPI Rx logic.

    LT8618SXB_I2C_Write_Byte(0x13, 0xf1);
    LT8618SXB_I2C_Write_Byte(0x13, 0xf9); // Reset TTL video process
}

/***********************************************************

***********************************************************/
void LT8618SXB_TTL_Input_Analog(void)
{
    // TTL mode
    LT8618SXB_I2C_Write_Byte(0xff, 0x81); // register bank
    LT8618SXB_I2C_Write_Byte(0x02, 0x66);
    LT8618SXB_I2C_Write_Byte(0x0a, 0x06);
    LT8618SXB_I2C_Write_Byte(0x15, 0x06);

	//LT8618SXB_I2C_Write_Byte(0x4e, 0xa8); // for U2
	LT8618SXB_I2C_Write_Byte(0x4e, 0x00); // for U3

    LT8618SXB_I2C_Write_Byte(0xff, 0x82);
    LT8618SXB_I2C_Write_Byte(0x1b, 0x77);
    LT8618SXB_I2C_Write_Byte(0x1c, 0xEC); // 25000
}

u8 ttl_input_val = 0x40;
/***********************************************************

***********************************************************/
void LT8618SXB_TTL_Input_Digtal(void)
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x80);

#ifdef _HV_mode_Only_
    LT8618SXB_I2C_Write_Byte(0x0A, 0xa0);         // bit5=1 : Internal generate DE control logic clock enable
#else
#ifdef _De_mode_Only_
    LT8618SXB_I2C_Write_Byte(0x0A, 0x90);         // bit4=1 : Internal generate sync control logic clock enable
#else
    LT8618SXB_I2C_Write_Byte(0x0A, 0x80);         // normal
#endif
#endif

    // TTL_Input_Digtal
    LT8618SXB_I2C_Write_Byte(0xff, 0x82);         // register bank
    LT8618SXB_I2C_Write_Byte(0x45, _TTL_BGR_);    //RGB channel swap

#if 0
    if(USE_DDRCLK == 1)
    {
        LT8618SXB_I2C_Write_Byte(0x4f, 0x80);     //0x00;  0x40: dclk
    }else
    {
        LT8618SXB_I2C_Write_Byte(0x4f, 0x40);     //0x00;  0x40: dclk
    }
#else
    Debug_Printf("LT8618SXB_I2C_Write_Byte(0x4f, %x);\n", ttl_input_val);
    LT8618SXB_I2C_Write_Byte(0x4f, ttl_input_val);     //0x00;  0x40: dclk
#endif

    LT8618SXB_I2C_Write_Byte(0x50, 0x00);
	LT8618SXB_I2C_Write_Byte(0x51, 0x00);

#ifdef _HV_mode_Only_
    LT8618SXB_I2C_Write_Byte(0x47, 0x87);         // bit7=1 : TTL output de from internal generated signal enable
#endif

#ifdef _De_mode_Only_
    LT8618SXB_I2C_Write_Byte(0x47, 0x47);         // bit6=1 : TTL output sync from internal generated signal enable
#endif

#ifdef _DE_Sync_mode_
    LT8618SXB_I2C_Write_Byte(0x47, 0x07);         // bit6=1 : TTL output sync from internal generated signal enable
#endif
}

/***********************************************************

***********************************************************/
#ifndef _DE_Sync_mode_

void LT8618SX_Timing_Set(void)
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x82);
    LT8618SXB_I2C_Write_Byte(0x2c, (u8)(Format_Timing[Resolution_Num][H_tol] / 256));
    LT8618SXB_I2C_Write_Byte(0x2d, (u8)(Format_Timing[Resolution_Num][H_tol] % 256));
    LT8618SXB_I2C_Write_Byte(0x2e, (u8)(Format_Timing[Resolution_Num][H_act] / 256));
    LT8618SXB_I2C_Write_Byte(0x2f, (u8)(Format_Timing[Resolution_Num][H_act] % 256));
    LT8618SXB_I2C_Write_Byte(0x30, (u8)(Format_Timing[Resolution_Num][H_fp] / 256));
    LT8618SXB_I2C_Write_Byte(0x31, (u8)(Format_Timing[Resolution_Num][H_fp] % 256));
    LT8618SXB_I2C_Write_Byte(0x32, (u8)(Format_Timing[Resolution_Num][H_bp] / 256));
    LT8618SXB_I2C_Write_Byte(0x33, (u8)(Format_Timing[Resolution_Num][H_bp] % 256));
    LT8618SXB_I2C_Write_Byte(0x34, (u8)(Format_Timing[Resolution_Num][H_sync] / 256));
    LT8618SXB_I2C_Write_Byte(0x35, (u8)(Format_Timing[Resolution_Num][H_sync] % 256));

    LT8618SXB_I2C_Write_Byte(0x36, (u8)(Format_Timing[Resolution_Num][V_act] / 256));
    LT8618SXB_I2C_Write_Byte(0x37, (u8)(Format_Timing[Resolution_Num][V_act] % 256));
    LT8618SXB_I2C_Write_Byte(0x38, (u8)(Format_Timing[Resolution_Num][V_fp] / 256));
    LT8618SXB_I2C_Write_Byte(0x39, (u8)(Format_Timing[Resolution_Num][V_fp] % 256));
    LT8618SXB_I2C_Write_Byte(0x3a, (u8)(Format_Timing[Resolution_Num][V_bp] / 256));
    LT8618SXB_I2C_Write_Byte(0x3b, (u8)(Format_Timing[Resolution_Num][V_bp] % 256));
    LT8618SXB_I2C_Write_Byte(0x3c, (u8)(Format_Timing[Resolution_Num][V_sync] / 256));
    LT8618SXB_I2C_Write_Byte(0x3d, (u8)(Format_Timing[Resolution_Num][V_sync] % 256));
}

#endif


/***********************************************************

***********************************************************/
// The threshold value of high HPD detected by lt8618sxb is 1.2V
u8 LT8618SXB_HPD_status(void)
{
    u8 HPD_Status = 0;

    LT8618SXB_I2C_Write_Byte(0xff, 0x82); // Register bank

    if((LT8618SXB_I2C_Read_Byte(0x5e) & 0x05) == 0x05)
    {
        HPD_Status = 1;                     // HPD is High
    }

    return HPD_Status;
}

//------------------------------------------------------------

void LT8618SXB_HDMI_TX_En(bool enable)
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x81);
    if(enable)
    {
        LT8618SXB_I2C_Write_Byte(0x30, 0xea);
    }else
    {
        LT8618SXB_I2C_Write_Byte(0x30, 0x00);
    }
}

/***********************************************************

***********************************************************/
// for debug
void LT8618SXB_Video_Check(void)
{
    u8      temp;
    bool    vs_pol, hs_pol;

    vs_pol = 0;
    hs_pol = 0;

    Delay_ms(100);

    LT8618SXB_I2C_Write_Byte(0xff, 0x82); //video check

    temp = LT8618SXB_I2C_Read_Byte(0x70); //hs vs polarity

    if(temp & 0x02)
    {
        vs_pol = 1;
    }
    if(temp & 0x01)
    {
        hs_pol = 1;
    }

    vs_width = LT8618SXB_I2C_Read_Byte(0x71);

    hs_width = LT8618SXB_I2C_Read_Byte(0x72) * 0x100 + LT8618SXB_I2C_Read_Byte(0x73);

    vbp    = LT8618SXB_I2C_Read_Byte(0x74);
    vfp    = LT8618SXB_I2C_Read_Byte(0x75);

    hbp = LT8618SXB_I2C_Read_Byte(0x76) * 0x100 + LT8618SXB_I2C_Read_Byte(0x77);

    hfp = LT8618SXB_I2C_Read_Byte(0x78) * 0x100 + LT8618SXB_I2C_Read_Byte(0x79);

    v_tal = LT8618SXB_I2C_Read_Byte(0x7a) * 0x100 + LT8618SXB_I2C_Read_Byte(0x7b);

    h_tal = LT8618SXB_I2C_Read_Byte(0x7c) * 0x100 + LT8618SXB_I2C_Read_Byte(0x7d);

    v_act = LT8618SXB_I2C_Read_Byte(0x7e) * 0x100 + LT8618SXB_I2C_Read_Byte(0x7f);

    h_act = LT8618SXB_I2C_Read_Byte(0x80) * 0x100 + LT8618SXB_I2C_Read_Byte(0x81);

    CLK_Cnt = (LT8618SXB_I2C_Read_Byte(0x1d) & 0x0f) * 0x10000 + LT8618SXB_I2C_Read_Byte(0x1e) * 0x100 + LT8618SXB_I2C_Read_Byte(0x1f);
    // Pixel CLK =  CLK_Cnt * 1000

    Debug_Printf("h_FrontPorch = %d\n", hfp);
    Debug_Printf("h_SyncWidth = %d\n", hs_width);
    Debug_Printf("h_BackPorch = %d\n", hbp);
    Debug_Printf("h_active = %d\n", h_act);
    Debug_Printf("h_total = %d\n", h_tal);

    Debug_Printf("v_FrontPorch = %d\n", vfp);
    Debug_Printf("v_SyncWidth = %d\n", vs_width);
    Debug_Printf("v_BackPorch = %d\n", vbp);
    Debug_Printf("v_active = %d\n", v_act);
    Debug_Printf("v_total = %d\n", v_tal);
}

/***********************************************************

***********************************************************/
u32 LT8618SX_CLK_Det(void)
{
	u32 dclk_;
	HDMI_WriteI2C_Byte(0xff,0x82);
	HDMI_WriteI2C_Byte(0x17,0x80);
	Delay_ms(500);
	dclk_=(((HDMI_ReadI2C_Byte(0x1d))&0x0f)<<8)+HDMI_ReadI2C_Byte(0x1e);
	dclk_=(dclk_<<8)+HDMI_ReadI2C_Byte(0x1f);
	Debug_Printf("\r\n ad ttl dclk = %d",dclk_);
	return dclk_;
}

bool LT8618SX_PLL_Version_U3(void)
{
	u8 read_val;
	u8 j;
	u8 cali_done;
	u8 cali_val;
	u8 lock;
	u32 dclk;

	dclk=LT8618SX_CLK_Det();

	if(USE_DDRCLK == 1)
	{
	 dclk=dclk*2;
	}

    //if(Video_Input_Mode==Input_RGB_12BIT||Video_Input_Mode==Input_RGB888 || Video_Input_Mode==Input_YCbCr444||Video_Input_Mode==Input_YCbCr422_16BIT||Video_Input_Mode==Input_BT1120_16BIT)
    {
		LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
		LT8618SXB_I2C_Write_Byte( 0x23, 0x40 );
		LT8618SXB_I2C_Write_Byte( 0x24, 0x62 );         //0x62(u3) ,0x64 icp set
		LT8618SXB_I2C_Write_Byte( 0x25, 0x00 );         //prediv=div(n+1)
		LT8618SXB_I2C_Write_Byte( 0x2c, 0x9e );
		//if(INPUT_IDCK_CLK==_Less_than_50M)
		if(dclk<50000)
		{
			LT8618SXB_I2C_Write_Byte( 0x2d, 0xaa );       //[5:4]divx_set //[1:0]freq set
			Debug_Printf("\r\nPLL LOW");
		}
		//else if(INPUT_IDCK_CLK==_Bound_50_100M)
		else if((dclk>50000)&&(dclk<100000))
		{
			LT8618SXB_I2C_Write_Byte( 0x2d, 0x99 );       //[5:4] divx_set //[1:0]freq set
			Debug_Printf("\r\nPLL MID");
		}
		//else if(INPUT_IDCK_CLK==_Greater_than_100M)
		else
		{
			LT8618SXB_I2C_Write_Byte( 0x2d, 0x88 );       //[5:4] divx_set //[1:0]freq set
			Debug_Printf("\r\nPLL HIGH");
		}
		LT8618SXB_I2C_Write_Byte( 0x26, 0x55 );
		LT8618SXB_I2C_Write_Byte( 0x27, 0x66 );   //phase selection for d_clk
		LT8618SXB_I2C_Write_Byte( 0x28, 0x88 );

		LT8618SXB_I2C_Write_Byte( 0x29, 0x04 );   //for U3 for U3 SDR/DDR fixed phase

    }

	LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
	read_val=LT8618SXB_I2C_Read_Byte(0x2b);
	LT8618SXB_I2C_Write_Byte( 0x2b, read_val&0xfd );// sw_en_txpll_cal_en
	read_val=LT8618SXB_I2C_Read_Byte(0x2e);
	LT8618SXB_I2C_Write_Byte( 0x2e, read_val&0xfe );//sw_en_txpll_iband_set

	LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
	LT8618SXB_I2C_Write_Byte( 0xde, 0x00 );
	LT8618SXB_I2C_Write_Byte( 0xde, 0xc0 );

	LT8618SXB_I2C_Write_Byte( 0xff, 0x80 );
	LT8618SXB_I2C_Write_Byte( 0x16, 0xf1 );
	LT8618SXB_I2C_Write_Byte( 0x18, 0xdc );//txpll _sw_rst_n
	LT8618SXB_I2C_Write_Byte( 0x18, 0xfc );
	LT8618SXB_I2C_Write_Byte( 0x16, 0xf3 );

	if(USE_DDRCLK == 1)
	{
		LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
		LT8618SXB_I2C_Write_Byte( 0x27, 0x60 );   //phase selection for d_clk
		LT8618SXB_I2C_Write_Byte( 0x4d, 0x05 );//
		LT8618SXB_I2C_Write_Byte( 0x2a, 0x10 );//
		LT8618SXB_I2C_Write_Byte( 0x2a, 0x30 );//sync rest
	}
	else
	{
		LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
		LT8618SXB_I2C_Write_Byte( 0x27, 0x66 );   //phase selection for d_clk
		LT8618SXB_I2C_Write_Byte( 0x2a, 0x00 );//
		LT8618SXB_I2C_Write_Byte( 0x2a, 0x20 );//sync rest
	}
	for(j=0;j<0x05;j++)
	{
		Delay_ms(10);
		LT8618SXB_I2C_Write_Byte(0xff,0x80);
		LT8618SXB_I2C_Write_Byte(0x16,0xe3); /* pll lock logic reset */
		LT8618SXB_I2C_Write_Byte(0x16,0xf3);

		LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
		lock=0x80&LT8618SXB_I2C_Read_Byte(0x15);
		cali_val=LT8618SXB_I2C_Read_Byte(0xea);
		cali_done=0x80&LT8618SXB_I2C_Read_Byte(0xeb);
		if(lock&&cali_done&&(cali_val!=0xff))
		{
			#ifdef _DEBUG_MODE
			LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
			Debug_Printf("\r\n0x8215=%bx",LT8618SXB_I2C_Read_Byte(0x15));
			Debug_Printf("\r\n0x82e6=%bx",LT8618SXB_I2C_Read_Byte(0xe6));
			Debug_Printf("\r\n0x82e7=%bx",LT8618SXB_I2C_Read_Byte(0xe7));
			Debug_Printf("\r\n0x82e8=%bx",LT8618SXB_I2C_Read_Byte(0xe8));
			Debug_Printf("\r\n0x82e9=%bx",LT8618SXB_I2C_Read_Byte(0xe9));
			Debug_Printf("\r\n0x82ea=%bx",LT8618SXB_I2C_Read_Byte(0xea));
			Debug_Printf("\r\n0x82eb=%bx",LT8618SXB_I2C_Read_Byte(0xeb));
			Debug_Printf("\r\n0x82ec=%bx",LT8618SXB_I2C_Read_Byte(0xec));
			Debug_Printf("\r\n0x82ed=%bx",LT8618SXB_I2C_Read_Byte(0xed));
			Debug_Printf("\r\n0x82ee=%bx",LT8618SXB_I2C_Read_Byte(0xee));
			Debug_Printf("\r\n0x82ef=%bx",LT8618SXB_I2C_Read_Byte(0xef));
			#endif
			Debug_Printf("\r\nTXPLL Lock");

			if(USE_DDRCLK == 1)
			{
				LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
				LT8618SXB_I2C_Write_Byte( 0x4d, 0x05 );//
				LT8618SXB_I2C_Write_Byte( 0x2a, 0x10 );//
				LT8618SXB_I2C_Write_Byte( 0x2a, 0x30 );//sync rest
			}
			else
			{
				LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
				LT8618SXB_I2C_Write_Byte( 0x2a, 0x00 );//
				LT8618SXB_I2C_Write_Byte( 0x2a, 0x20 );//sync rest
			}
			return 1;
		}
		else
		{
			LT8618SXB_I2C_Write_Byte( 0xff, 0x80 );
			LT8618SXB_I2C_Write_Byte( 0x16, 0xf1 );
			LT8618SXB_I2C_Write_Byte( 0x18, 0xdc );//txpll _sw_rst_n
			LT8618SXB_I2C_Write_Byte( 0x18, 0xfc );
			LT8618SXB_I2C_Write_Byte( 0x16, 0xf3 );
			Debug_Printf("\r\nTXPLL Reset");
		}
	}
	Debug_Printf("\r\nTXPLL Unlock");
	return 0;
}

#if 1
bool LT8618SX_PLL_Version_U2(void)
{
	u8 read_val;
	u8 j;
	u8 cali_done;
	u8 cali_val;
	u8 lock;
	u32 dclk;

	dclk=LT8618SX_CLK_Det();

	//if(Video_Input_Mode==Input_RGB888 || Video_Input_Mode==Input_YCbCr444||Video_Input_Mode==Input_YCbCr422_16BIT||Video_Input_Mode==Input_BT1120_16BIT)
	{
		LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
		LT8618SXB_I2C_Write_Byte( 0x23, 0x40 );
		LT8618SXB_I2C_Write_Byte( 0x24, 0x62 );               //icp set
		LT8618SXB_I2C_Write_Byte( 0x26, 0x55 );

		if(dclk<=25000)
		{
			LT8618SXB_I2C_Write_Byte( 0x25, 0x00 );
			//LT8618SXB_I2C_Write_Byte( 0x2c, 0xA8 );
			LT8618SXB_I2C_Write_Byte( 0x2c, 0x94 );
			LT8618SXB_I2C_Write_Byte( 0x2d, 0xaa );
		}
		else if((dclk>25000)&&(dclk<=50000))
		{
			LT8618SXB_I2C_Write_Byte( 0x25, 0x00 );
			LT8618SXB_I2C_Write_Byte( 0x2d, 0xaa );
			LT8618SXB_I2C_Write_Byte( 0x2c, 0x94 );
		}
		else if((dclk>50000)&&(dclk<=100000))
		{
			LT8618SXB_I2C_Write_Byte( 0x25, 0x01 );
			LT8618SXB_I2C_Write_Byte( 0x2d, 0x99 );
			LT8618SXB_I2C_Write_Byte( 0x2c, 0x94 );

			Debug_Printf("\r\n50~100m");
		}

		else //if(dclk>100000)
		{
			LT8618SXB_I2C_Write_Byte( 0x25, 0x03 );
			LT8618SXB_I2C_Write_Byte( 0x2d, 0x88 );
			LT8618SXB_I2C_Write_Byte( 0x2c, 0x94 );
		}

		if( USE_DDRCLK )
		{
			read_val=LT8618SXB_I2C_Read_Byte(0x2c) &0x7f;
			read_val=read_val*2|0x80;
			LT8618SXB_I2C_Write_Byte( 0x2c, read_val );
			Debug_Printf("\r\n0x812c=%x",(u16)read_val);
			LT8618SXB_I2C_Write_Byte( 0x4d, 0x05 );
			LT8618SXB_I2C_Write_Byte( 0x27, 0x66 );                                               //0x60 //ddr 0x66
			LT8618SXB_I2C_Write_Byte( 0x28, 0x88 );
			Debug_Printf("\r\n PLL DDR" );
		}
		else
		{
			LT8618SXB_I2C_Write_Byte( 0x4d, 0x01 );
			LT8618SXB_I2C_Write_Byte( 0x27, 0x60 ); //0x06                                              //0x60 //ddr 0x66
			LT8618SXB_I2C_Write_Byte( 0x28, 0x88 );                                               // 0x88
			Debug_Printf("\r\n PLL SDR" );
		}
	}


	// as long as changing the resolution or changing the input clock,	You need to configure the following registers.
	LT8618SXB_I2C_Write_Byte( 0xff, 0x81 );
	read_val=LT8618SXB_I2C_Read_Byte(0x2b);
	LT8618SXB_I2C_Write_Byte( 0x2b, read_val&0xfd );// sw_en_txpll_cal_en
	read_val=LT8618SXB_I2C_Read_Byte(0x2e);
	LT8618SXB_I2C_Write_Byte( 0x2e, read_val&0xfe );//sw_en_txpll_iband_set

	LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
	LT8618SXB_I2C_Write_Byte( 0xde, 0x00 );
	LT8618SXB_I2C_Write_Byte( 0xde, 0xc0 );

	LT8618SXB_I2C_Write_Byte( 0xff, 0x80 );
	LT8618SXB_I2C_Write_Byte( 0x16, 0xf1 );
	LT8618SXB_I2C_Write_Byte( 0x18, 0xdc );//txpll _sw_rst_n
	LT8618SXB_I2C_Write_Byte( 0x18, 0xfc );
	LT8618SXB_I2C_Write_Byte( 0x16, 0xf3 );
	for(j=0;j<0x05;j++)
	{
		Delay_ms(10);
		LT8618SXB_I2C_Write_Byte(0xff,0x80);
		LT8618SXB_I2C_Write_Byte(0x16,0xe3); /* pll lock logic reset */
		LT8618SXB_I2C_Write_Byte(0x16,0xf3);

		LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
		lock=0x80&LT8618SXB_I2C_Read_Byte(0x15);
		cali_val=LT8618SXB_I2C_Read_Byte(0xea);
		cali_done=0x80&LT8618SXB_I2C_Read_Byte(0xeb);
		if(lock&&cali_done&&(cali_val!=0xff))
		{
			#ifdef _DEBUG_MODE
			LT8618SXB_I2C_Write_Byte( 0xff, 0x82 );
			Debug_Printf("\r\n0x82ea=%bx",LT8618SXB_I2C_Read_Byte(0xea));
			Debug_Printf("\r\n0x82eb=%bx",LT8618SXB_I2C_Read_Byte(0xeb));
			Debug_Printf("\r\n0x82ec=%bx",LT8618SXB_I2C_Read_Byte(0xec));
			Debug_Printf("\r\n0x82ed=%bx",LT8618SXB_I2C_Read_Byte(0xed));
			Debug_Printf("\r\n0x82ee=%bx",LT8618SXB_I2C_Read_Byte(0xee));
			Debug_Printf("\r\n0x82ef=%bx",LT8618SXB_I2C_Read_Byte(0xef));
			#endif
			Debug_Printf("\r\nTXPLL Lock");
			return 1;
		}
		else
		{
			LT8618SXB_I2C_Write_Byte( 0xff, 0x80 );
			LT8618SXB_I2C_Write_Byte( 0x16, 0xf1 );
			LT8618SXB_I2C_Write_Byte( 0x18, 0xdc );//txpll _sw_rst_n
			LT8618SXB_I2C_Write_Byte( 0x18, 0xfc );
			LT8618SXB_I2C_Write_Byte( 0x16, 0xf3 );
			Debug_Printf("\r\nTXPLL Reset");
		}
	}
	Debug_Printf("\r\nTXPLL Unlock");
	return 0;
}
#endif

void LT8618SXB_PLL_config(void)
{
    u8  read_val;
	LT8618SXB_I2C_Write_Byte(0xff,0x80);
	read_val=LT8618SXB_I2C_Read_Byte(0x02);//get IC Version
  if(read_val==0xe1)
	{
	 LT8618SX_PLL_Version_U2();
	 Debug_Printf("\r\nchip u2c");
	}
	else if(read_val==0xe2)
	{
	 LT8618SX_PLL_Version_U3();
	 Debug_Printf("\r\nchip u3c");
	}
	else
	{
	 Debug_Printf("\r\nfail version=%x",read_val);
	}
}

/***********************************************************

***********************************************************/
#ifdef _DVI_
void LT8618SXB_DVI_setting(void)
{
    LT8618SXB_I2C_Write_Byte(0xff, 0x82); // register bank
    LT8618SXB_I2C_Write_Byte(0xd6, 0x0e); // bit7 = 0 : DVI output; bit7 = 1: HDMI output
}

#else


/***********************************************************
***********************************************************/
void LT8618SXB_Audio_setting(void)
{
//----------------IIS-----------------------
    // IIS Input
    LT8618SXB_I2C_Write_Byte(0xff, 0x82); // register bank
    LT8618SXB_I2C_Write_Byte(0xd6, 0x8e); // bit7 = 0 : DVI output; bit7 = 1: HDMI output
    LT8618SXB_I2C_Write_Byte(0xd7, 0x04); // sync polarity

    LT8618SXB_I2C_Write_Byte(0xff, 0x84); // register bank
    LT8618SXB_I2C_Write_Byte(0x06, 0x08);
    LT8618SXB_I2C_Write_Byte(0x07, 0x10); // SD0 channel selected

    LT8618SXB_I2C_Write_Byte(0x09, 0x00); // 0x00 :Left justified; default
    // 0x02 :Right justified;

//-----------------SPDIF---------------------


    /*  SPDIF Input
       LT8618SXB_I2C_Write_Byte(0xff, 0x82);// register bank
       LT8618SXB_I2C_Write_Byte(0xd6, 0x8e);
       LT8618SXB_I2C_Write_Byte(0xd7, 0x00);  //sync polarity

       LT8618SXB_I2C_Write_Byte(0xff, 0x84);// register bank
       LT8618SXB_I2C_Write_Byte(0x06, 0x0c);
       LT8618SXB_I2C_Write_Byte(0x07, 0x10);
       //*/

//-------------------------------------------

    LT8618SXB_I2C_Write_Byte(0x0f, 0x0b + Sample_Freq[_48KHz]);

// 根据音频数据长度的不同，设置不同的寄存器值。
    LT8618SXB_I2C_Write_Byte(0x34, 0xd4); //CTS_N / 2; 32bit
//  LT8618SXB_I2C_Write_Byte(0x34, 0xd5); //CTS_N / 4; 16bit

    LT8618SXB_I2C_Write_Byte(0x35, (u8)(IIS_N[_48KHz] / 0x10000));
    LT8618SXB_I2C_Write_Byte(0x36, (u8)((IIS_N[_48KHz] & 0x00FFFF) / 0x100));
    LT8618SXB_I2C_Write_Byte(0x37, (u8)(IIS_N[_48KHz] & 0x0000FF));

    LT8618SXB_I2C_Write_Byte(0x3c, 0x21); // Null packet enable
}

#endif
// LT8618SXB only supports three color space convert: YUV422, yuv444 and rgb888.
// Color space convert of YUV420 is not supported.
void LT8618SXB_CSC_setting(void)
{
    // color space config
    LT8618SXB_I2C_Write_Byte(0xff, 0x82); // register bank
//  LT8618SXB_I2C_Write_Byte(0xb9, 0x08);// YCbCr444 to RGB
//  LT8618SXB_I2C_Write_Byte(0xb9, 0x18);// YCbCr422 to RGB

//  LT8618SXB_I2C_Write_Byte(0xb9, 0x80);// RGB to YCbCr444
//  LT8618SXB_I2C_Write_Byte(0xb9, 0xa0);// RGB to YCbCr422

//  LT8618SXB_I2C_Write_Byte(0xb9, 0x10);// YCbCr422 to YCbCr444
//  LT8618SXB_I2C_Write_Byte(0xb9, 0x20);// YCbCr444 to YCbCr422

    LT8618SXB_I2C_Write_Byte(0xb9, 0x00); // No csc
}

/***********************************************************

***********************************************************/
#ifdef _HDMI_
void LT8618SXB_AVI_setting(void)
{
    //AVI
    u8  AVI_PB0    = 0x00;
    u8  AVI_PB1    = 0x00;
    u8  AVI_PB2    = 0x00;


    /********************************************************************************
       The 0x43 register is checksums,
       changing the value of the 0x45 or 0x47 register,
       and the value of the 0x43 register is also changed.
       0x43, 0x44, 0x45, and 0x47 are the sum of the four register values is 0x6F.
     *********************************************************************************/

//  VIC_Num = 0x04; // 720P 60; Corresponding to the resolution to be output
//  VIC_Num = 0x10; // 1080P 60
//  VIC_Num = 0x1F; // 1080P 50
//  VIC_Num = 0x5F; // 4K30

//================================================================//

    // Please refer to function: void LT8618SXB_CSC_setting(void)


    /****************************************************
       Because the color space of RGB888 signal is RGB,
       if lt8618sxb does not do color space convert (no CSC),
       the color space of output HDMI is RGB.
     *****************************************************/

    AVI_PB1 = 0x10;                                     // PB1,color space: YUV444 0x50;YUV422 0x30; RGB 0x10

//===============================================================//

    AVI_PB2 = Format_Timing[Resolution_Num][Pic_Ratio]; // PB2; picture aspect rate
//  AVI_PB2 = 0x2A; // PB2; picture aspect rate: 0x2A : 16:9 // Such as : 720P / 1080P / 40K30 / 1600x900
//  AVI_PB2 = 0x19; // PB2; picture aspect rate: 0x19 : 4:3 // Such as : 640x480 / 1024x768 / 1280x1024

    AVI_PB0 = ((AVI_PB1 + AVI_PB2 + VIC_Num) <= 0x6f) ? (0x6f - AVI_PB1 - AVI_PB2 - VIC_Num) : (0x16f - AVI_PB1 - AVI_PB2 - VIC_Num);

    LT8618SXB_I2C_Write_Byte(0xff, 0x84);             // register bank
    LT8618SXB_I2C_Write_Byte(0x43, AVI_PB0);          // PB0,avi packet checksum
    LT8618SXB_I2C_Write_Byte(0x44, AVI_PB1);          // PB1,color space: YUV444 0x50;YUV422 0x30; RGB 0x10
    LT8618SXB_I2C_Write_Byte(0x45, AVI_PB2);          // PB2;picture aspect rate: 0x19:4:3 ; 0x2A : 16:9
    LT8618SXB_I2C_Write_Byte(0x47, VIC_Num);          // PB4;vic ,0x10: 1080P ;  0x04 : 720P

//  LT8618SXB_I2C_Write_Byte(0xff,0x84);
//  8618SXB hdcp1.4 加密的话，要保证hfp + 8410[5:0](rg_island_tr_res) 的个数（video de的下降沿到 最近的一个aude 的间隔），大于58；hdcp1.4 spec中有要求
    LT8618SXB_I2C_Write_Byte(0x10, 0x2c);             //data iland
    LT8618SXB_I2C_Write_Byte(0x12, 0x64);             //act_h_blank

    //VS_IF, 4k 30hz need send VS_IF packet. Please refer to hdmi1.4 spec 8.2.3
    if(VIC_Num == 95)
    {
//     LT8618SXB_I2C_Write_Byte(0xff,0x84);
        LT8618SXB_I2C_Write_Byte(0x3d, 0x2a);         //UD1 infoframe enable

        LT8618SXB_I2C_Write_Byte(0x74, 0x81);
        LT8618SXB_I2C_Write_Byte(0x75, 0x01);
        LT8618SXB_I2C_Write_Byte(0x76, 0x05);
        LT8618SXB_I2C_Write_Byte(0x77, 0x49);
        LT8618SXB_I2C_Write_Byte(0x78, 0x03);
        LT8618SXB_I2C_Write_Byte(0x79, 0x0c);
        LT8618SXB_I2C_Write_Byte(0x7a, 0x00);
        LT8618SXB_I2C_Write_Byte(0x7b, 0x20);
        LT8618SXB_I2C_Write_Byte(0x7c, 0x01);
    }else
    {
//     LT8618SXB_I2C_Write_Byte(0xff,0x84);
        LT8618SXB_I2C_Write_Byte(0x3d, 0x0a); //UD1 infoframe disable
    }
}

#endif

#define AC_SWING_VAL    0xe0 /*往上调， b0 c0 e0 这样子 */

#define AC_EMPHASIS_VAL 0x80
/*
7'b00000000 = 0 mA
7'b00000001 = 0.0625 mA
7'b00000010 = 0.125 mA
7'b00000100 = 0.25 mA
7'b00001000 = 0.5 mA
7'b00010000 = 1 mA
7'b00100000 = 2 mA
7'b10000000 = 4 mA
*/

/***********************************************************

***********************************************************/
void LT8618SXB_TX_Phy(void)
{
    char val;

    // HDMI_TX_Phy
    LT8618SXB_I2C_Write_Byte(0xff, 0x81); // register bank

#if 1
    LT8618SXB_I2C_Write_Byte(0x30, 0xea);

    Debug_Printf("DC mode\n");
    LT8618SXB_I2C_Write_Byte(0x31, 0x44);
    LT8618SXB_I2C_Write_Byte(0x32, 0x4a);
    LT8618SXB_I2C_Write_Byte(0x33, 0x0b);

    /********************************/
    val = AC_EMPHASIS_VAL;
    Debug_Printf("X--AC_EMPHASIS_VAL : %x\n", val);
    LT8618SXB_I2C_Write_Byte(0x34, 0x00);
    LT8618SXB_I2C_Write_Byte(0x35, 0x00);
    LT8618SXB_I2C_Write_Byte(0x36, 0x00);

    // same with other mode
    LT8618SXB_I2C_Write_Byte(0x37, 0x44);
    LT8618SXB_I2C_Write_Byte(0x3f, 0x0f);


    /********************************/
    LT8618SXB_I2C_Write_Byte(0x40, 0xa0); //0xa0 -- CLK tap0 swing
    LT8618SXB_I2C_Write_Byte(0x41, 0xa0); //0xa0 -- D0 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x42, 0xa0); //0xa0 -- D1 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x43, 0xa0); //0xa0 -- D2 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x44, 0x0a);
#else // AC mode
    // 0x8130= 0xff 代表打开swing和预加重
    LT8618SXB_I2C_Write_Byte(0x30, 0xff); // 0xea
    Debug_Printf("AC mode\n");
    LT8618SXB_I2C_Write_Byte(0x31, 0x73);
    LT8618SXB_I2C_Write_Byte(0x32, 0xea);
    LT8618SXB_I2C_Write_Byte(0x33, 0x4a);

    val = AC_EMPHASIS_VAL;
    Debug_Printf("AC_EMPHASIS_VAL : %x\n", val);
    LT8618SXB_I2C_Write_Byte(0x34, val);
    LT8618SXB_I2C_Write_Byte(0x35, val);
    LT8618SXB_I2C_Write_Byte(0x36, val);

    // same with other mode
    LT8618SXB_I2C_Write_Byte(0x37, 0x44);
    LT8618SXB_I2C_Write_Byte(0x3f, 0x0f);

    /********************************/
    val = AC_SWING_VAL;
    Debug_Printf("AC_SWING_VAL : %x\n", val);
    LT8618SXB_I2C_Write_Byte(0x40, val); //0xa0 -- CLK tap0 swing
    LT8618SXB_I2C_Write_Byte(0x41, val); //0xa0 -- D0 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x42, val); //0xa0 -- D1 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x43, val); //0xa0 -- D2 tap0 swing
    LT8618SXB_I2C_Write_Byte(0x44, val);
#endif


}

//******************************************************//


int resolution_str_to_num(char *str)
{
    int ret;
    int ret_default = _4K30_;

    ret = ret_default;

    if(str == NULL)
    {
        goto end;
    }
    if(strcmp(str,"480P60") == 0)
    {
        ret = _480P60_;
        goto end;
    }
    if(strcmp(str,"576P50") == 0)
    {
        ret = _576P50_;
        goto end;
    }
    if(strcmp(str,"720P60") == 0)
    {
        ret = _720P60_;
        goto end;
    }

    if(strcmp(str,"720P30") == 0)
    {
        ret = _720P30_;
        goto end;
    }

    if(strcmp(str,"720P25") == 0)
    {
        ret = _720P25_;
        goto end;
    }

    if(strcmp(str,"1080P60") == 0)
    {
        ret = _1080P60_;
        goto end;
    }

    if(strcmp(str,"1080P50") == 0)
    {
        ret = _1080P50_;
        goto end;
    }

    if(strcmp(str,"1080P30") == 0)
    {
        ret = _1080P30_;
        goto end;
    }

    if(strcmp(str,"1080P25") == 0)
    {
        ret = _1080P25_;
        goto end;
    }

    if(strcmp(str,"1080i60") == 0)
    {
        ret = _1080i60_;
        goto end;
    }

    if(strcmp(str,"1080i50") == 0)
    {
        ret = _1080i50_;
        goto end;
    }

    if(strcmp(str,"4K30") == 0)
    {
        ret = _4K30_;
        goto end;
    }

    if(strcmp(str,"800x600P60") == 0)
    {
        ret = _800x600P60_;
        goto end;
    }

    if(strcmp(str,"1024x768P60") == 0)
    {
        ret = _1024x768P60_;
        goto end;
    }

    if(strcmp(str,"1024x600P60") == 0)
    {
        ret = _1024x600P60_;
        goto end;
    }

end:
    Debug_Printf("Using [%s]\n", str);
    return ret;
}

// Step:

// 1、Reset LT8618SX

// 2、LT8618SX Initial setting:

int main(int argc, char *argv[])
{
    int tmp_value;
    int i2c_bus = 2;
    char *resolution_type = "4K30";
    // ARGV[1] ：分辨率
    if(argc >= 2)
    {
        resolution_type = argv[1];
    }
    // ARGV[2] : I2C总线
    if(argc >= 3)
    {
        i2c_bus = atoi(argv[2]);
    }
    // ARGV[3] : 7位设备地址
    if(argc >= 4)
    {
        sscanf(argv[3], "%x", &tmp_value);
        //dev_addr = atoi(argv[2]);
        I2CADR =  tmp_value << 1;
    }
    // ARGV[4] : 0x4f val
    if(argc >= 5)
    {
        sscanf(argv[4], "%x", &tmp_value);
        //dev_addr = atoi(argv[2]);
        ttl_input_val =  tmp_value;
    }
    tmp_value = 1;
    printf("%d: resolution_type %s\n", tmp_value++, resolution_type);
    printf("%d: i2c_bus         %d\n", tmp_value++, i2c_bus);
    printf("%d: I2CADR          %x\n", tmp_value++, I2CADR >> 1);
    printf("%d: ttl_input_val   %x\n", tmp_value++, ttl_input_val);
    init_i2c(i2c_bus);

    USE_DDRCLK = 0;                                                                 // 1: DDR mode; 0: SDR (normal) mode
    printf("USE_DDRCLK = %d  \t\t1: DDR mode; 0: SDR (normal) mode \n", USE_DDRCLK);

    // According to the input different resolution, set the following parameters(Resolution_Num).
    // If there is no corresponding resolution in the array, you need to add it manually.
    Resolution_Num = resolution_str_to_num(resolution_type);

    CLK_bound = Format_Timing[Resolution_Num][Clk_bound_SDR + (u8)(USE_DDRCLK)];  // Parameters required by LT8618SXB_PLL_setting(void)

    VIC_Num = Format_Timing[Resolution_Num][Vic];                                   // Parameters required by LT8618SXB_AVI_setting(void)


    LT8618SXB_Chip_ID();                   // for debug

    LT8618SXB_Video_Check();   // For debug

    return 0;
}

// When the lt8618sxb works, the resolution of the TTL signal changes.
// The following settings need to be configured.
void Resolution_change(u8 Resolution)
{
    Resolution_Num = Resolution;                                                    // Parameters required by LT8618SXB_BT_Timing_setting(void)

    CLK_bound = Format_Timing[Resolution_Num][Clk_bound_SDR + (u8)(USE_DDRCLK)];  // Parameters required by LT8618SXB_PLL_setting(void)

    VIC_Num = Format_Timing[Resolution_Num][Vic];

    LT8618SXB_PLL_config();

#ifndef _DE_Sync_mode_
    LT8618SX_Timing_Set();
#endif

    LT8618SXB_AVI_setting();
}

/************************************** The End Of File **************************************/
